perm filename PUPR.C[11,HE] blob
sn#688205 filedate 1982-12-06 generic text, type T, neo UTF8
/* LINTLIBRARY */
/*
* pupread.c
*
* Reads a pup packet and returns the information in it.
* Since a lot of this information is superfluous, the user
* can pass NULL as the address for the data to be returned
* for any item(s) not wanted. The input parameters are
* guaranteed not to be altered unless the return status
* is OK, or the status is BADCKSUM and the channel status
* includes PCM_IGNBADCKS.
*
* Jeffrey Mogul & Dan Kolkowitz 12-January-1981
*
* modified JCM 30-June-1981 -- neglected to return bad status
*
*/
#include <puppacket.h>
#include <pupconstants.h>
#include <pupstatus.h>
pupread(Pchan,buf,buflen, Ptype, ID, DstPort, SrcPort)
struct PupChan *Pchan; /* channel to use */
char *buf; /* data buffer */
int *buflen; /* data buffer length */
uchar *Ptype; /* Pup type */
ulong *ID; /* Pup ID */
struct Port *DstPort; /* destination port */
struct Port *SrcPort; /* source port */
{
struct EnPacket enpack; /* ether encapsulation */
int readstat;
int rlen; /* rounded length of pup data */
/*
* here we would switch on the Chan->transport to
* determine which lower-level encapsulation to use
* if there were any choice.
*/
#ifdef VAX
if (Pchan->TimeoutSet)
readstat = enreadquick(Pchan->ifid, & enpack, NULL);
else { /* must set timeout */
readstat = enread(Pchan->ifid, & enpack, NULL, Pchan->timeout);
Pchan->TimeoutSet = 1;
}
#else
readstat = enread(Pchan->ifid, & enpack, &(Pchan->filter.en),
Pchan->timeout);
#endif
if (readstat==OK) { /* return all information requested */
rlen = roundup(enpack.Pup.PupLength) - PUPACKOVER;
if (rlen < 0) /* avoid negative length copies */
return(NOTAPUP);
/*
* check the pup checksum if necessary.
* If the checksum is bad, set the status to BADCKSUM.
* If the channel mode include IGNBADCKS and the checksum
* is bad, don't modify any params.
*/
if (Pchan->mode&PCM_RCHECKSUM) {
ushort cksum = *(short *)&enpack.Pup.PupData[rlen];
if (cksum != NOCKSUM &&
cksum != checksum(&enpack.Pup,rlen+PUPACKOVER-2)) {
readstat = BADCKSUM;
if (Pchan->mode&PCM_IGNBADCKS)
return(readstat);
}
}
/*
* return each parameter iff reference address is not NULL
*/
if (SrcPort) {
PortUnpack(&enpack.Pup.PupSrc, SrcPort);
}
if (DstPort) {
PortUnpack(&enpack.Pup.PupDst, DstPort);
}
if (ID) *ID = getlong(enpack.Pup.PupID);
if (Ptype) *Ptype = enpack.Pup.PupType;
if (buflen) *buflen = enpack.Pup.PupLength - PUPACKOVER;
/* return unrounded length */
if (buf) { /* return buffer to user */
bmove(enpack.Pup.PupData,buf,rlen);
#ifdef PUP__NNSO /* nonstandard byte order */
if (Pchan->mode&PCM_RFIXLAST)
/* swap last word in buffer if odd length */
if (enpack.Pup.PupLength&1) {
/* swap garbage byte */
buf[enpack.Pup.PupLength-1] =
buf[enpack.Pup.PupLength];
}
#else /* no trouble for standard byte order */
#endif
}
return(readstat);
}
return(readstat);
}